Imports System.Web.UI
Imports System.ComponentModel
Imports System.Drawing
Imports System.Collections.Generic

Namespace DotNetNuke.UI.WebControls
    Public Class ScriptGenerator

        Public Shared Function GetMarshalledPropertyJSON(ByVal instance As Object) As String
            Dim properties As Hashtable = New Hashtable() 'GetMarshalledProperties(instance)
            Return GetMarshalledPropertyJSON(instance, properties)
        End Function

        Public Shared Function GetMarshalledPropertyJSON(ByVal instance As Object, ByVal properties As Hashtable) As String
            Return ToJSON(GetMarshalledProperties(instance, properties))
        End Function

        Public Shared Function GetMarshalledProperties(ByVal instance As Object) As Hashtable
            Return GetMarshalledProperties(instance, New Hashtable)
        End Function

        Public Shared Function GetMarshalledProperties(ByVal instance As Object, ByVal properties As Hashtable) As Hashtable
            Dim propAttr As ClientPropertyAttribute = Nothing
            Dim nameAttr As ClientPropertyNameAttribute = Nothing
            Dim eventAttr As ClientEventAttribute = Nothing

            Dim urlResolver As IUrlResolutionService = CType(instance, IUrlResolutionService)
            'Dim controlResolver As IControlResolver = CType(instance, IControlResolver)

            Dim propName As String = ""
            Dim shouldSerialize As Boolean
            Dim props As PropertyDescriptorCollection = TypeDescriptor.GetProperties(instance)
            Dim processProp As Boolean
            For Each prop As PropertyDescriptor In props
                propAttr = TryCast(prop.Attributes(GetType(ClientPropertyAttribute)), ClientPropertyAttribute)
                processProp = True
                If propAttr Is Nothing Then
                    'Look for other attributes (events)
                    eventAttr = TryCast(prop.Attributes(GetType(ClientEventAttribute)), ClientEventAttribute)
                    If eventAttr Is Nothing Then
                        processProp = False
                    End If
                End If

                If processProp Then
                    'figure out if it should be renamed
                    propName = prop.Name
                    nameAttr = TryCast(prop.Attributes(GetType(ClientPropertyNameAttribute)), ClientPropertyNameAttribute)
                    If Not nameAttr Is Nothing Then
                        propName = nameAttr.Name
                    End If

                    'determine if value is default and should be serialized
                    shouldSerialize = prop.ShouldSerializeValue(instance) OrElse prop.IsReadOnly
                    If shouldSerialize Then
                        'get property value
                        Dim value As Object = prop.GetValue(instance)

                        If Not eventAttr Is Nothing AndAlso Not prop.PropertyType Is GetType(String) Then
                            Throw New Exception("Events properties can only be of type string")
                        Else
                            If Not prop.PropertyType.IsPrimitive AndAlso Not prop.PropertyType.IsEnum Then
                                If prop.PropertyType Is GetType(Color) Then
                                    value = ColorTranslator.ToHtml(CType(value, Color))
                                End If
                            End If

                            'smaller to marshal 0/1 than True/False
                            If prop.PropertyType Is GetType(Boolean) Then
                                If CBool(value) Then
                                    value = "1"
                                Else
                                    value = "0"
                                End If
                            End If
                            'resolve urls (~/sub/)
                            If Not prop.Attributes(GetType(UrlPropertyAttribute)) Is Nothing AndAlso Not urlResolver Is Nothing AndAlso Not value Is Nothing Then
                                If TypeOf instance Is Control Then
                                    value = CType(instance, Control).ResolveUrl(CStr(value))
                                Else
                                    value = urlResolver.ResolveClientUrl(CStr(value))
                                End If
                            End If

                            'If prop.PropertyType Is GetType(String) OrElse prop.PropertyType Is GetType(Date) Then
                            'Everything will be treated as a string for now... that is the way it was as expando props!
                            'If Not value Is Nothing Then
                            '    value = "'" & CStr(value).Replace("'", "\'") & "'"
                            'Else
                            '    value = "''"
                            'End If
                            If prop.PropertyType Is GetType(Char) Then
                                'When char is nothing, it doesn't report itself as such
                                If Asc(CChar(value)) <> 0 Then
                                    properties.Add(propName, value)
                                End If
                            Else
                                If Not value Is Nothing Then
                                    If Not eventAttr Is Nothing Then
                                        properties.Add(propName, CStr(value))
                                    Else
                                        properties.Add(propName, value)
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next
            Return properties
        End Function

    End Class
End Namespace
